package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemClient;
import com.hmall.common.client.UserClient;
import com.hmall.common.pojo.Address;
import com.hmall.common.pojo.Item;
import com.hmall.common.pojo.User;
import com.hmall.context.BaseContext;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDTO;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    OrderLogisticsMapper orderLogisticsMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 新增订单
     *
     * @param orderDTO
     * @return
     */
    @GlobalTransactional
    @Override
    public Long addOrder(OrderDTO orderDTO) {
        Long userId = BaseContext.getCurrentId();

        //调用商品微服务，计算totalFee
        Item item = itemClient.getById(orderDTO.getItemId());
        if (item == null) {
            throw new RuntimeException("商品不存在或已下架");
        }
        Long totalFee = orderDTO.getNum() * item.getPrice();
        //封装订单数据，添加order
        Order order = Order.builder()
                .totalFee(totalFee)
                .paymentType(orderDTO.getPaymentType())
                .userId(userId)
                .status(1)
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        int insertOrderCount = orderMapper.insert(order);
        Long orderId = order.getId();

        //调用用户微服务：获取用户信息及用户地址
        Address address = userClient.findAddressById(orderDTO.getAddressId());
        User user = userClient.findById(userId);
        //封装订单地址数据，添加orderLogistics
        OrderLogistics orderLogistics = OrderLogistics.builder()
                .orderId(orderId)
                .contact(user.getUsername())
                .mobile(user.getPhone())
                .province(address.getProvince())
                .city(address.getCity())
                .town(address.getTown())
                .street(address.getStreet())
                .updateTime(new Date())
                .createTime(new Date())
                .build();
        int insertLogisticsCount = orderLogisticsMapper.insert(orderLogistics);

        //封装订单详情数据，添加orderDetail
        OrderDetail orderDetail = OrderDetail.builder()
                .orderId(orderId)
                .itemId(orderDTO.getItemId())
                .num(orderDTO.getNum())
                .name(item.getName())
                .spec(item.getSpec())
                .price(item.getPrice())
                .image(item.getImage())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        int insertDetailCount = orderDetailMapper.insert(orderDetail);

        if (insertDetailCount == 0 || insertOrderCount == 0 || insertLogisticsCount == 0) {
            throw new RuntimeException("订单创建失败");
        }

        //扣减库存
        itemClient.stock(orderDTO.getItemId(),orderDTO.getNum());

        //发送消息给延时队列，处理超时未支付订单(30min，改为15秒方便测试)
        Message message = MessageBuilder
                .withBody(orderId.toString().getBytes(StandardCharsets.UTF_8))
                .setHeader("x-delay", 15000)
                //.setHeader("x-delay", 30 * 60 * 1000)
                .build();
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("delay.direct", "delay", message, correlationData);

        return orderId;
    }
}
